Azure ADでリフレッシュトークンを取得してアクセストークンを更新する
いわさです。
以前の記事で、Azure ADでアクセストークンを取得し、UserInfoエンドポイントへアクセスしてみました。
アクセストークンには有効期限があります。
上記記事で取得したアクセストークンの有効期限は約1~1.5時間ほどでした。
一定間隔でサインインが必要になってしまうので、今回はリフレッシュトークンを使ってみたいと思います。
リフレッシュトークンについては、稲葉純さんの以下の記事で触れられております。
また、Microsoft IDプラットフォームの更新トークンの既定の有効期間は90日で、かつ使用されるたびに新しいトークンに置き換えられます。
このあたりは、都元ダイスケさんが以下の記事内でもリフレッシュトークンの再発行によるセッション期間について言及されています。
リフレッシュトークンの取得条件
まず、前回の方法でアクセストークン取得時の状況を確認してみます。
どうやらリフレッシュトークンは取得されていないようですね。
リフレッシュトークンを取得するためにはいくつか条件があります。
まず、前回まで使用していた暗黙的な(インプリシット)フローではリフレッシュトークンは提供されません。
前回はauthorize
エンドポイントを使ってIDトークンとアクセストークンを同時に取得していましたが、token
エンドポイントを使った承認コードフローを使う必要があります。
そして、更新トークンを受信するには、アプリがoffline_access
スコープを明示的に要求する必要があります。
指定しなかった場合は、エンドポイントからアクセストークンだけが取得されます。
リフレッシュトークンを取得する
スコープでoffline_access
を設定
先程の条件にあったようにoffline_access
をスコープで指定した時にリフレッシュトークンが提供されます。
Azureポータル上で許可設定を行っておきます。
承認コード取得
テナントIDとクライアントIDを指定してブラウザでアクセスします。
Azure ADのサインイン画面で認証操作を行うと、承認コードがパラメータに付与されてリダイレクトされると思います。
https://login.microsoftonline.com/11111111-2222-3333-4444-555555555555/oauth2/v2.0/authorize?client_id=66666666-7777-8888-9999-000000000000&response_type=code&response_mode=query&scope=user.read+openid+profile+email&state=12345
このコードを使って、次はアクセストークンを取得します。
アクセストークン & リフレッシュトークン取得
アクセス時にシークレットあるいは証明書が必要です。
ここではAzure ADアプリケーション上でシークレットを作成し、それを利用しました。
iwasa.takahito@hoge 20211220azuread % curl -X POST -d 'client_id=66666666-7777-8888-9999-000000000000' -d 'code=<承認コード>' -d 'grant_type=authorization_code' -d 'client_secret=<シークレット>' -d 'scope=user.read+openid+profile+email+offline_access' https://login.microsoftonline.com/11111111-2222-3333-4444-555555555555/oauth2/v2.0/token | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 7080 100 5568 100 1512 8224 2233 --:--:-- --:--:-- --:--:-- 10442 { "token_type": "Bearer", "scope": "email openid profile User.Read", "expires_in": 5107, "ext_expires_in": 5107, "access_token": "<アクセストークン>", "refresh_token": "<リフレッシュトークン>", "id_token": "<IDトークン>" }
アクセストークンにあわせてリフレッシュトークンが取得出来ました。
まずは、アクセストークンを解析してみましょう。
Microsoftより提供されているJWT.MSを使います。
{ "typ": "JWT", ... }.{ "aud": "00000003-0000-0000-c000-000000000000", "iss": "https://sts.windows.net/", "iat": 1639980148, "nbf": 1639980148, "exp": 1639985556, "acct": 0, "acr": "1", "aio": "***", "altsecid": "1:live.com:*******", "amr": [ "pwd", "mfa" ], ... }.[Signature]
有効期限は、2021年12月20日 16:32:36
でした。
リフレッシュトークンを使ってアクセストークンを更新する
リフレッシュトークンを使う際にはtoken
エンドポイントにリフレッシュトークンをパラメータに設定し、grant_type
はrefresh_token
を指定します。
iwasa.takahito@hoge 20211220azuread % curl -X POST -d 'client_id=66666666-7777-8888-9999-000000000000' -d 'refresh_token=<リフレッシュトークン>' -d 'grant_type=refresh_token' -d 'client_secret=<シークレット>' -d 'scope=user.read+openid+profile+email+offline_access' https://login.microsoftonline.com/11111111-2222-3333-4444-555555555555/oauth2/v2.0/token | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 7492 100 5574 100 1918 8736 3006 --:--:-- --:--:-- --:--:-- 11724 { "token_type": "Bearer", "scope": "email openid profile User.Read", "expires_in": 5294, "ext_expires_in": 5294, "access_token": "<新アクセストークン>", "refresh_token": "<新リフレッシュトークン>", "id_token": "<IDトークン>" }
新しいアクセストークンが取得出来ました。
先程と同じ手順で期限を確認してみると、2021年12月20日 17:08:18
でした。
UserInfoエンドポイントへアクセスしてみましょう。
iwasa.takahito@hoge 20211220azuread % curl -H 'Authorization: Bearer <新しいアクセストークン>' https://graph.microsoft.com/oidc/userinfo | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 182 0 182 0 0 846 0 --:--:-- --:--:-- --:--:-- 846 { "sub": "HOGE", "name": "いわさ", "family_name": "いわ", "given_name": "さ", "picture": "https://graph.microsoft.com/v1.0/me/photo/$value" }
UserInfoを取得することが出来ましたね。
古いアクセストークンは使えるのでしょうか。
iwasa.takahito@hoge 20211220azuread % curl -H 'Authorization: Bearer <古いアクセストークン>' https://graph.microsoft.com/oidc/userinfo | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 182 0 182 0 0 579 0 --:--:-- --:--:-- --:--:-- 579 { "sub": "HOGE", "name": "いわさ", "family_name": "いわ", "given_name": "さ", "picture": "https://graph.microsoft.com/v1.0/me/photo/$value" }
古いアクセストークンも期限までは引き続きアクセス可能です。
また、新しいリフレッシュトークンも提供されていましたね。
Microsoft IDプラットフォームでは、期限内の古いトークンは無効になりません。
詳細は以下を参照頂くのが良いですが、新しいトークンを取得出来たらサーバー側で安全に削除してくださいね。となっています。
さいごに
本日は、Azure ADのアクセストークンをリフレッシュトークンを使って更新する方法を紹介しました。
Webでリフレッシュトークンについて調べると、更新に使ったリフレッシュトークンが無効になるIdPもありました。このあたりは実装によるようですね。
Microsoft IDプラットフォームでは無効にならない。とおぼえておきましょう。